<?php
namespace app\common\MobileVerify;
use app\common\MobileVerify\SignatureHelper;
use think\facade\Cache;
class MobileVerify{
    private $mobile_code_expiration_time =300;//指定时间内重复发送验证码，随机数设置相同（防止短信服务商通知堵塞，用户收到几条不同的验证码，难以识别哪个是最后的）
    public $error;//错误
    public $mobile;
    public $isTest;//开启调试模式会在程序根目录生成code.txt，验证码在这里，可以通过url访问code.txt查看验证码
    //参数
    public function __construct(){
    }
    //获取6位随机验证码
    public function get_rand($mobile){
        if(Cache::get('verify_mobile'. $mobile )==$mobile&&Cache::get("verify_mobile_code". $mobile )&&Cache::get("verify_mobile_expiration_time". $mobile )>time()){
            return Cache::get('verify_mobile_code'. $mobile );
        }else{
            Cache::set('verify_mobile' . $mobile , $mobile, 300);
            $randnum=rand(1000,9999);
            //这里是临时测试发送的
            if($this->isTest){
                $randnum=8888;
            }
            Cache::set("verify_mobile_code". $mobile ,$randnum, 300);
            Cache::set("verify_mobile_expiration_time". $mobile ,time()+$this->mobile_code_expiration_time, 300);
            return $randnum;
        }
    }
    //验证上次发送是否为50秒之前
    public function verify_lasttime($mobile){
        if(Cache::get("verify_mobile_last_sendtime". $mobile )&&(time()-Cache::get("verify_mobile_last_sendtime". $mobile ))<50){
            return false;
        }
        return true;
    }
    //发送验证码
    public function send_code($mobile){

        $code=$this->get_rand($mobile);
        if(!$this->verify_lasttime($mobile)){
            $this->error="请不要恶意获取验证码";
            return false;
        }
        // 开始发送
        $result=$this->sendSms($mobile,$code);
        //获取发送结果
        if($result->Code!='OK'){
            $this->error="短信发送失败，错误代码：".$result->Code;
        }else{
            //
            Cache::set('verify_mobile_last_sendtime'. $mobile,time(),300);//最后发送时间
            return true;
        }
    }
    //验证码检验
    public function check($mobile,$code){
        if(Cache::get('verify_mobile'. $mobile)!=$mobile||Cache::get('verify_mobile_code'. $mobile)!=$code){
            $this->error="短信验证码错误";
            return false;
        }
        if((Cache::get('verify_mobile_last_sendtime'. $mobile)+1800)<time()){
            $this->error="短信验证码已经过期";
            return false;
        }
        $this->clear($mobile);
        return true;
    }
    //清除验证码相关数据
    public function clear($mobile){
        Cache::delete('verify_mobile'. $mobile);
        Cache::delete('verify_mobile_code'. $mobile);
        Cache::delete('verify_mobile_expiration_time'. $mobile);
        Cache::delete('verify_mobile_last_sendtime'. $mobile);
    }
    // 发送短信
    public function sendSms($mobile,$code) {
        $params = array ();
        $SMS=Config("mobile");//从配置文件读取短信配置参数
        // *** 需用户填写部分 ***
        // fixme 必填: 请参阅 https://ak-console.aliyun.com/ 取得您的AK信息
        $accessKeyId = $SMS["accessKeyId"];

        $accessKeySecret = $SMS["accessKeySecret"];

        // fixme 必填: 短信接收号码
        $params["PhoneNumbers"] = $mobile;

        // fixme 必填: 短信签名，应严格按"签名名称"填写，请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/sign
        $params["SignName"] = $SMS["SignName"];

        // fixme 必填: 短信模板Code，应严格按"模板CODE"填写, 请参考: https://dysms.console.aliyun.com/dysms.htm#/develop/template
        $params["TemplateCode"] = $SMS["TemplateCode"];

        // fixme 可选: 设置模板参数, 假如模板中存在变量需要替换则为必填项
        $params['TemplateParam'] = Array (
            "code" => $code
        );
        // *** 需用户填写部分结束, 以下代码若无必要无需更改 ***
        if(!empty($params["TemplateParam"]) && is_array($params["TemplateParam"])) {

            if(version_compare(PHP_VERSION,'5.4.0','<')){
                $params["TemplateParam"] = json_encode($params["TemplateParam"]);
                $params["TemplateParam"] = preg_replace_callback("#\\\u([0-9a-f]{4})#i",function($matchs){
                    return iconv('UCS-2BE', 'UTF-8', pack('H4', $matchs[1]));
                },$params["TemplateParam"]);
            }else{
                $params["TemplateParam"] = json_encode($params["TemplateParam"], JSON_UNESCAPED_UNICODE);
            }
        }

        // 初始化SignatureHelper实例用于设置参数，签名以及发送请求
        $helper = new SignatureHelper();

        // 此处可能会抛出异常，注意catch
        $content = $helper->request(
            $accessKeyId,
            $accessKeySecret,
            "dysmsapi.aliyuncs.com",
            array_merge($params, array(
                "RegionId" => "cn-hangzhou",
                "Action" => "SendSms",
                "Version" => "2017-05-25",
            ))
        );

        return $content;
    }
}
